home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK2.toast / Development Kits (Disc 2) / ScriptX / Draggable ScriptX Folders / utils / widgets / popupmnu.sx < prev    next >
Encoding:
Text File  |  1995-12-11  |  8.6 KB  |  353 lines  |  [TEXT/ttxt]

  1. --<<<-
  2.  
  3. global PopUpButton
  4.  
  5. class PopUpMenu(Menu)
  6. class variables
  7.     mouse:(new MouseDevice)
  8. instance variables
  9.     selectAction
  10.     authorData:(undefined)
  11.     _selectedLine:0
  12.     selection
  13.     
  14.     upInterest
  15.     
  16.     stepAmount:0
  17.     tempPoint:(new Point)
  18.     frame:(new Frame)
  19.     _list
  20. end
  21.  
  22. method init self {class PopUpMenu} #rest args #key    \
  23.     width:                                            \
  24.     boundary:                                        \
  25.     list:(#())                                        \
  26.     font:(theSystemFont)                            ->
  27. (
  28.     self.stepAmount := font.leading
  29.     if (boundary == unsupplied) then
  30.         boundary := new Rect x2:width y2:(font.leading+2)
  31.     else if (width != unsupplied) do
  32.         boundary.width := width
  33.     local targetPresenter := apply new ListBox width:boundary.width args    
  34.     apply NextMethod self boundary:boundary actuatorController:undefined \
  35.         targetPresenter:targetPresenter layoutController:undefined args
  36.     self.selection := new ListSelection font:font \
  37.         width:self.width parent:targetPresenter
  38.     self.list := list
  39.         
  40.     local upInterest := new MouseUpEvent
  41.     self.upInterest := upInterest
  42.     upInterest.eventReceiver := upReceiver;
  43.     upInterest.buttons := @mouseButton1
  44.     upInterest.authordata := self
  45.     upInterest.presenter := undefined -- global move interest -- not associated with presenter
  46.     upInterest.priority := 6
  47. )
  48.  
  49. method afterInit self {class PopUpMenu} #rest args ->
  50. (
  51.     apply NextMethod self args
  52.     local cp := self.clippingPresenter
  53.     InsetRect cp.boundary 2 2 @mutate
  54.     cp.stationary := true
  55.     cp.fill := ColorScheme.grayBrushes[4]
  56.     self.stationary := true
  57.     self.horizScrollBarDisplayed := self.vertScrollBarDisplayed := @none
  58.     self.selectedLine := 1
  59. )
  60.  
  61. method draw self {class PopUpMenu} surface clip ->
  62. (
  63.     NextMethod self surface clip
  64.     drawRaisedFrame self.frame surface clip self.globalTransform
  65. )
  66.  
  67. method recalcRegion self {class PopUpMenu} ->
  68. (
  69.     NextMethod self
  70.     SetBoundary self.frame self.boundary
  71. )
  72.  
  73. method tickle self {class PopUpMenu} clock ->
  74. (
  75.     local targetP := self.targetPresenter
  76.     local tempPoint := self.tempPoint
  77.     local screenCoords := PopUpMenu.mouse.currentCoords
  78.     setTo tempPoint screenCoords
  79.     ScreenToDisplay self.window.displaySurface tempPoint @mutate
  80.     SurfaceToLocal self tempPoint @mutate
  81.     local bbox := self.clippingPresenter.boundary
  82.     local y1 := bbox.y1
  83.     local y2 := bbox.y2
  84.     local mouseY := tempPoint.y
  85.     local sel := self.selection
  86.     
  87.     if (inside bbox tempPoint) then
  88.         show sel
  89.     else
  90.         hide sel
  91.     if (mouseY < y1) then (
  92.         if (self._selectedLine > 0) do
  93.             repeatScrollAction self targetP @up
  94.     )
  95.     else if (mouseY > y2) then (
  96.         if (self._selectedLine < self.numLines) do (
  97.             repeatScrollAction self targetP @down
  98.         )
  99.     )
  100.     else (
  101.         LocalToSurface self tempPoint @mutate
  102.         SurfaceToLocal targetP tempPoint @mutate
  103.         self.selectedLine := \
  104.             (((tempPoint.y - 2)/self.stepAmount) as ImmediateInteger) + 1
  105.     )
  106. )
  107.  
  108. method repeatScrollAction self {class PopUpMenu} targetPresenter direction ->
  109. (
  110.     local y  := -targetpresenter.y
  111.     local newY := self.stepAmount
  112.     if (direction = @up) then (
  113.         newY := y - newY
  114.     )
  115.     else if (direction = @down) do (
  116.         newY := y + newY
  117.     )
  118.         scrollTo self 0 newY
  119. )
  120.  
  121. method upReceiver self {class PopUpMenu} theInterest event ->
  122. (
  123.     self.needsTickle := false
  124.     removeEventInterest self.upInterest
  125.     local sel := self.selection
  126.     if (sel.isVisible) then (
  127.         local invoker := self.invoker
  128.         local selectAction := self.selectAction
  129.         if (selectAction != undefined) do
  130.             selectAction self.authorData self._selectedLine
  131.         if (isAKindOf invoker PopUpButton) do (
  132.             invoker.value := self.value
  133.         )
  134.     )
  135.     else (
  136.         show sel
  137.     )
  138.     hide self
  139.     @accept
  140. )
  141.  
  142. method layout self {class PopUpMenu} ->
  143. (
  144.     NextMethod self
  145.     local cp := self.clippingPresenter
  146.     cp.width := cp.width - 4
  147.     cp.height := cp.height - 4
  148.     self
  149. )
  150.  
  151. method popUp self {class PopUpMenu} invoker superMenu point ->
  152. (
  153.     NextMethod self invoker superMenu point
  154.     self.needsTickle := true
  155.     addEventInterest self.upInterest
  156. )
  157.     
  158. method calculateSize self {class PopUpMenu} ->
  159. (
  160.     local invoker := self.invoker
  161.     local topPresenter := invoker.window
  162.     if (topPresenter != undefined) do (
  163.         local targetP := self.targetPresenter
  164.         local targetHt := targetP.height
  165.         local topHt := topPresenter.height
  166.         if (targetHt > topHt ) then
  167.             self.height := topHt
  168.         else
  169.             self.height := targetHt
  170.     )
  171. )
  172.  
  173. method place self {class PopUpMenu} pt ->
  174. (
  175.     NextMethod self pt
  176.     local invoker := self.invoker
  177.     if (isAKindOf invoker PopUpButton) do (
  178.         local y := self.y
  179.         local invokerY := invoker.y
  180.         if (y > invokerY) do (
  181.             self.y := invokerY + 3
  182.         )
  183.         self.x := invoker.x + 3
  184.     )
  185. )
  186.  
  187. method fontGetter self {class PopUpMenu} -> self.targetPresenter.font
  188. method fontSetter self {class PopUpMenu} newFont ->
  189. (
  190.     self.targetPresenter.font := newFont
  191.     self.stepAmount := newFont.leading
  192.     changeFont self.selection newFont self._selectedLine
  193.     layout self
  194.     newFont
  195. )
  196.  
  197.  
  198. method selectedLineGetter self {class PopUpMenu} ->
  199.     self._selectedLine
  200.  
  201. method selectedLineSetter self {class PopUpMenu} newLine -> 
  202. (
  203.     if (newLine <> self._selectedLine and newLine > 0 and \
  204.         newLine <= self.numLines ) then (
  205.         ThreadCriticalUp()
  206.         selectLine self.selection newLine @dontAction
  207.         self._selectedLine := newLine
  208.         local lineHt := self.stepAmount
  209.         local startLine := round(-self.targetPresenter.y/lineHt) + 1
  210.         local endLine := \
  211.             (startLine + (self.height - 5 + lineHt)/lineHt - 1) as ImmediateInteger
  212.         if (newLine < startLine or newLine >= endLine) do (
  213.             ScrollTo self 0 ((newLine - 1)*lineHt)
  214.         )
  215.         ThreadCriticalDown()
  216.     )
  217.     newLine
  218. )
  219.  
  220. method numLinesGetter self {class PopUpMenu} -> self.targetPresenter.numLines
  221.  
  222. method widthSetter self {class PopUpMenu} newWidth->
  223. (
  224.     self.selection.width := newWidth
  225.     self.targetPresenter.width := newWidth
  226.     NextMethod self newWidth
  227. )
  228.  
  229. method valueGetter self {class PopUpMenu} ->
  230. (
  231.     GetNthKey self._list self._selectedLine
  232. )
  233.  
  234. method valueSetter self {class PopUpMenu} newValue ->
  235. (
  236.     local scrollList := self._list
  237.     self.selectedLine := (GetOrdOne scrollList newValue)
  238.     newValue
  239. )
  240.     
  241. method listGetter self {class PopUpMenu} -> self._list
  242. method listSetter self {class PopUpMenu} newList ->
  243. (
  244.     self._list := self.targetPresenter.list := newList
  245.     self.selectedLine := 1
  246.     layout self
  247.     newList
  248. )    
  249.  
  250. method fillGetter self {class PopUpMenu} -> self.clippingPresenter.fill
  251. method fillSetter self {class PopUpMenu} newFill ->
  252. (
  253.     self.clippingPresenter.fill := newFill
  254.     NextMethod self undefined
  255. )
  256.  
  257. class PopUpButton(TextButton)
  258. class variables
  259.     popPict:(importDIB "media/popup.bmp")
  260. end
  261.  
  262. method init self {class PopUpButton} #rest args #key\
  263.     boundary: menu: \
  264.     value: ->
  265. (
  266.     apply NextMethod self stencil:PopUPButton.popPict args
  267.     self.buttonFrame.scheme := menu.frame.scheme := theMenuScheme
  268.     self.font := menu.font
  269.     if (boundary == unsupplied) do (
  270.         self.width := menu.width + 6
  271.         self.height := menu.font.leading + 8
  272.     )
  273.     self.menu := menu
  274.     if (value != unsupplied) do (
  275.         local scrollList := menu._list
  276.         local item := GetOne scrollList value
  277.         self.text := item as Text
  278.         menu._selectedLine := (GetOrdOne scrollList item)
  279.     )
  280. )
  281.  
  282. method recalcRegion self {class PopUpButton} ->
  283. (
  284.     NextMethod self
  285.     local stencil := self._stencil
  286.     local border := self.border
  287.     local stencilTrans := self.stencilTransform
  288.     local gTrans := self.globalTransform
  289.     SetTo stencilTrans gTrans
  290.     local xOffset := border.x2 - stencil.width - 4
  291.     local yOffset := border.y1 + (border.height - stencil.height)/2
  292.     translate stencilTrans xOffset yOffset
  293.     local textTrans := self.textTransform
  294.     SetTo textTrans gTrans
  295.     local fontInfo := self.font
  296.     local leading := fontInfo.leading
  297.     local descent := fontInfo.descent
  298.     local yOffset := border.y1 + (border.height - 4 - leading) / 2 + leading - descent + 1
  299.     translate textTrans (border.x1 + 4) yOffset
  300. )
  301.  
  302. method draw self {class PopUpButton} surface clip ->
  303. (
  304.     if (not self.pressed) then
  305.         NextMethod self surface clip
  306.     else (
  307.         local transform := self.globalTransform
  308.         drawLoweredFrame self.recessedFrame surface clip transform
  309.         stroke surface self.border clip transform ColorScheme.grayBrushes[2]
  310.     )
  311. )
  312.  
  313. method menuSetter self {class PopUpButton} newMenu ->
  314. (
  315.     self.text := (GetOne newMenu._list newMenu.value) as Text
  316.     NextMethod self newMenu
  317. )
  318.  
  319. method widthSetter self {class PopUpButton} newWidth ->
  320. (
  321.     self.menu.width := newWidth - 6
  322.     NextMethod self newWidth
  323. )
  324.  
  325. method valueGetter self {class PopUpButton} -> self.menu.value
  326. method valueSetter self {class PopUpButton} newValue ->
  327. (
  328.     local menu := self.menu
  329.     menu.value := newValue
  330.     self.text := (GetOne menu._list newValue) as Text
  331.     newValue
  332. )
  333.  
  334. method fontSetter self {class PopUpButton} newFont ->
  335. (
  336.     NextMethod self newFont
  337.     self.menu.font := newFont
  338. )
  339.  
  340. method listGetter self {class PopUpButton} -> self.menu._list
  341. method listSetter self {class PopUpButton} newList ->
  342. (
  343.     local menu := self.menu
  344.     local val
  345.     
  346.     menu.list := newList
  347.     val := menu.value
  348.     self.text := (if (val == empty) then val else (GetOne menu._list val)) as Text
  349.     newList
  350. )
  351.  
  352. -->>>
  353.